<script lang="ts" setup>
  import type { CmsArticle, CmsAuthor } from '@/types/cms';
  import { onBeforeMount, onBeforeUnmount, onMounted, ref } from 'vue';
  import { Form, Message } from '@arco-design/web-vue';
  import {
    createArticle,
    updateArticle,
    getColumnList,
    getAuthorList,
    getArticleDetail,
  } from '@/api/cms';
  import ImageUpload from '@/components/image-upload/index.vue';
  import _ from 'lodash';
  import { CmsArticleTypes } from '@/config/cms';
  import dayjs from 'dayjs';
  import RichEditor from '@/components/rich-editor/index.vue';
  import { useAppStore } from '@/store';
  import { useRoute, useRouter } from 'vue-router';
  import scrollToFirstError from '@/utils/scroll-to-first-error';

  const appStore = useAppStore();

  onBeforeMount(() => {
    appStore.updateSettings({
      menu: false,
    });
  });

  onBeforeUnmount(() => {
    appStore.updateSettings({
      menu: true,
    });
  });

  const router = useRouter();
  const route = useRoute();

  const emit = defineEmits(['close']);

  const authorList = ref<CmsAuthor[]>([]);
  const handleSearchAuthor = async (content: string) => {
    const res = await getAuthorList({
      content,
      pageIndex: 1,
      pageSize: 100,
    });
    authorList.value = res.data.data.list || [];
  };

  const columnList = ref<
    {
      label: string;
      value: string;
    }[]
  >([]);
  const initColumnData = async () => {
    try {
      const res = await getColumnList({});
      columnList.value = (res.data.data || []).map((col) => ({
        label: col.columnName,
        value: col.id,
      }));
    } finally {
      // do nothing
    }
  };

  const data = ref<Partial<CmsArticle>>({});
  const loading = ref(false);
  onMounted(async () => {
    initColumnData();
    if (route.query.id) {
      loading.value = true;
      const articleRes = await getArticleDetail(route.query.id as string);
      const article = articleRes.data.data;
      data.value = {
        ...article,
        tagList: JSON.parse(article.tags || '[]') as string[],
        coverPicFileList: article.coverUrl
          ? [
              {
                status: 'done',
                uid: article.coverUrl,
                url: article.coverUrl,
                response: article.coverUrl,
              },
            ]
          : undefined,
      };
      handleSearchAuthor(data.value.cmsAuthor?.authorName || '');
      loading.value = false;
    } else {
      data.value = {
        contentType: 0,
        coinScoreRead: 0,
        coinScoreComment: 0,
        publishTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
      };
      handleSearchAuthor('');
    }
  });

  const publishing = ref(false);
  const saving = ref(false);
  const formRef = ref<InstanceType<typeof Form> | null>(null);
  const handleSubmit = async (state: number) => {
    if (formRef.value) {
      const validateResult = await formRef.value.validate();
      if (!validateResult) {
        const dataCloned = _.cloneDeep(data.value);
        dataCloned.state = state;
        if (
          dataCloned.coverPicFileList &&
          dataCloned.coverPicFileList[0]?.status === 'done'
        ) {
          dataCloned.coverUrl = dataCloned.coverPicFileList[0]?.response;
          delete dataCloned.coverPicFileList;
        } else {
          Message.warning('请上传封面图');
          return;
        }

        if (dataCloned.tagList) {
          dataCloned.tags = JSON.stringify(dataCloned.tagList);
          delete dataCloned.tagList;
        }

        if (state === 0) {
          saving.value = true;
        } else {
          publishing.value = true;
        }
        try {
          if (route.query.id) {
            await updateArticle({
              id: route.query.id as string,
              ...dataCloned,
            });
            Message.success('操作成功');
          } else {
            await createArticle(dataCloned);
            Message.success('操作成功');
          }
          setTimeout(() => {
            router.push({
              name: 'CmsArticleApp',
            });
          }, 2000);
        } finally {
          if (state === 0) {
            saving.value = true;
          } else {
            publishing.value = true;
          }
        }
      } else {
        scrollToFirstError(validateResult);
        Message.warning('信息填写有误，请检查');
      }
    }
  };
</script>

<template>
  <div class="article-editor">
    <div class="title">内容发布</div>
    <div>
      <a-form ref="formRef" :model="data" layout="vertical">
        <a-form-item
          label="标题"
          field="articleTitle"
          :rules="[{ required: true, message: '不能为空' }]"
        >
          <a-input v-model="data.articleTitle" />
        </a-form-item>

        <a-form-item label="摘要" field="articleAbstract">
          <a-textarea v-model="data.articleAbstract" />
        </a-form-item>

        <a-form-item
          label="作者"
          field="authorId"
          :rules="[{ required: true, message: '不能为空' }]"
        >
          <a-select
            v-model="data.authorId"
            allow-search
            :options="
              authorList.map((i) => ({ label: i.authorName, value: i.id }))
            "
            @search="handleSearchAuthor"
          ></a-select>
        </a-form-item>

        <a-form-item label="标签" field="tagList">
          <a-input-tag v-model="data.tagList" />
        </a-form-item>

        <a-form-item
          label="栏目"
          field="columnId"
          :rules="[{ required: true, message: '不能为空' }]"
        >
          <a-select v-model="data.columnId" :options="columnList"></a-select>
        </a-form-item>

        <a-form-item
          label="类型"
          field="contentType"
          :rules="[{ required: true, message: '不能为空' }]"
        >
          <a-select
            v-model="data.contentType"
            disabled
            :options="CmsArticleTypes"
          ></a-select>
        </a-form-item>

        <a-form-item
          label="封面图"
          field="coverPicFileList"
          :rules="[{ required: true, message: '不能为空' }]"
        >
          <ImageUpload
            v-model="data.coverPicFileList"
            :max-size="2 * 1024 * 1024"
            :limit="1"
            :should-square="false"
          />
          <template #extra>
            {{
              data.contentType === 1
                ? '请上传与视频比例一致的图片，'
                : '请上传长宽比接近1：1的图片，'
            }}不大于2MB
          </template>
        </a-form-item>

        <a-form-item
          label="发布时间"
          field="publishTime"
          :rules="[{ required: true, message: '不能为空' }]"
        >
          <a-date-picker
            v-model="data.publishTime"
            format="YYYY-MM-DD HH:mm:ss"
            show-time
          />
        </a-form-item>

        <a-form-item
          label="阅读送积分"
          field="coinScoreRead"
          :rules="[{ required: true, message: '不能为空' }]"
        >
          <a-input-number
            v-model="data.coinScoreRead"
            hide-button
            :precision="0"
            :min="0"
            :step="1"
          />
          <template #extra>阅读完成之后赠送多少积分</template>
        </a-form-item>

        <a-form-item
          label="评论送积分"
          field="coinScoreComment"
          :rules="[{ required: true, message: '不能为空' }]"
        >
          <a-input-number
            v-model="data.coinScoreComment"
            hide-button
            :precision="0"
            :min="0"
            :step="1"
          />
          <template #extra>发布一次评论赠送多少积分（仅赠送一次）</template>
        </a-form-item>

        <a-form-item v-if="!loading" hide-label field="content">
          <RichEditor v-model="data.content" />
        </a-form-item>
      </a-form>

      <div>
        <a-space>
          <a-button
            :loading="publishing"
            type="primary"
            @click="handleSubmit(1)"
          >
            立即发布
          </a-button>
          <a-button :loading="saving" @click="handleSubmit(0)">
            保存为草稿
          </a-button>
          <a-button @click="emit('close', false)">取消</a-button>
        </a-space>
      </div>
    </div>
  </div>
</template>

<style lang="less" scoped>
  .article-editor {
    width: 1000px;
    margin: 0 auto;
    background: #fff;
    padding: 20px;
    .title {
      font-size: 18px;
      margin-bottom: 20px;
    }
  }
</style>
